import { useEffect, useMemo, useRef, useState } from 'react'
import { useDebounceFn, useMemoizedFn, useUpdate } from 'ahooks'
import { Badge, Button, Checkbox, Input, Modal, Select, Space } from 'antd'

import { AgGridReact, CusAgGrid, ICusAgGridProps } from '@/components/CusAgGrid'
import { addAGCellTexty } from '@oBiz/components/addTexty'
import { RouteTplShow } from '@oBiz/components/FieldShowComponents'
import { getBooleanName, getLogisticsStatusName, getRouteNodeName, getRouteTypeName } from '@oBiz/TrackOrder/utils'
import { popupSlot } from '../../utils'
import { apiAddRoute, apiGetRouteList } from '../apis'
import { IRoute, TCellParams, TCol } from './interface'

const updatePopup = popupSlot.insert(null)

interface IAddRouteModalProps {
  waybillNo: string
  onSuccess?: () => void
}

const Cell = (p: TCellParams) => {
  const { field } = p.colDef || {}
  switch (field) {
    case 'templateCn':
    case 'templateEn': {
      const { value } = p as TCellParams<'templateCn' | 'templateEn'>
      return <RouteTplShow value={value} />
    }
    case 'routeType': {
      const { value, valueFormatted } = p as TCellParams<'routeType'>
      if (value == null) return
      return <Badge color={value === 1 ? 'green' : 'red'} text={valueFormatted || value} />
    }
    default: {
      return addAGCellTexty(p)
    }
  }
}

export const AddRouteModal = Object.assign(
  ({ waybillNo, onSuccess, destroy }: IAddRouteModalProps & { destroy: () => void }) => {
    const { open, onHide, afterOpenChange } = popupSlot.useAntdPopupAnimation(destroy)

    const [loading, setLoading] = useState(false)
    const [submitting, setSubmitting] = useState(false)
    const [data, setData] = useState<IRoute[]>([])
    const [selectedLen, setSelectedLen] = useState(0)

    const filterValueRef = useRef({
      templateCn: '',
      routeNode: null as number | null,
      logisticsStatus: null as number | null,
      onlySelected: false,
    })
    const update = useUpdate()
    const gridRef = useRef<AgGridReact<IRoute>>(null)

    // 列配置
    const defaultColDef = useMemo<Partial<TCol>>(
      () => ({
        flex: 1,
        minWidth: 130,
        sortable: false,
        cellRenderer: Cell,
      }),
      [],
    )
    const columnDefs = useMemo(
      () => [
        {
          field: 'routeNo',
          headerName: '路由编号',
          flex: 0.01,
          minWidth: 114,
        } satisfies TCol<'routeNo'>,
        {
          field: 'templateCn',
          headerName: '中文模板',
          flex: 2,
          minWidth: 210,
        } satisfies TCol<'templateCn'>,
        {
          field: 'templateEn',
          headerName: '英文模板',
          flex: 2,
          minWidth: 210,
        } satisfies TCol<'templateEn'>,
        {
          field: 'routeNode',
          headerName: '路由节点',
          valueFormatter: ({ value }) => getRouteNodeName(value) || '',
        } satisfies TCol<'routeNode'>,
        {
          field: 'logisticsStatus',
          headerName: '物流状态',
          flex: 0.01,
          minWidth: 114,
          valueFormatter: ({ value }) => getLogisticsStatusName(value) || '',
        } satisfies TCol<'logisticsStatus'>,
        {
          field: 'routeType',
          headerName: '路由类型',
          flex: 0.01,
          minWidth: 114,
          valueFormatter: ({ value }) => getRouteTypeName(value) || '',
        } satisfies TCol<'routeType'>,
        {
          field: 'actionFlag',
          headerName: '需跟进',
          flex: 0.01,
          minWidth: 100,
          valueFormatter: ({ value }) => getBooleanName(value) || '',
        } satisfies TCol<'actionFlag'>,
        {
          field: 'visibleFlag',
          headerName: '客户可见',
          flex: 0.01,
          minWidth: 114,
          valueFormatter: ({ value }) => getBooleanName(value) || '',
        } satisfies TCol<'visibleFlag'>,
      ],
      [],
    )

    // 行勾选
    const rowSelection = useMemo<ICusAgGridProps<IRoute>['rowSelection']>(() => {
      return { mode: 'multiRow', selectAll: 'filtered' }
    }, [])
    const onRowSelected = useMemoizedFn<NonNullable<ICusAgGridProps<IRoute>['onRowSelected']>>(() => {
      const selectedRows = gridRef.current?.api.getSelectedRows() || []
      setSelectedLen(selectedRows.length)
    })

    // 本地搜索
    const handleFilter = () => gridRef.current!.api.onFilterChanged()
    const { run: handleDebounceFilter } = useDebounceFn(handleFilter, { wait: 300 })
    const isExternalFilterPresent = useMemoizedFn<NonNullable<ICusAgGridProps['isExternalFilterPresent']>>(() => true)
    const doesExternalFilterPass = useMemoizedFn<NonNullable<ICusAgGridProps<IRoute>['doesExternalFilterPass']>>(
      node => {
        const { data } = node
        const templateCn = filterValueRef.current.templateCn.trim()
        const { routeNode, logisticsStatus, onlySelected } = filterValueRef.current
        if (logisticsStatus != null || routeNode != null || templateCn || onlySelected) {
          let hitTemplateCn = true
          let hitRouteNode = true
          let hitLogisticsStatus = true
          if (templateCn) {
            hitTemplateCn = !!data?.templateCn?.toLocaleLowerCase().includes(templateCn.toLocaleLowerCase())
          }
          if (routeNode != null) {
            hitRouteNode = data?.routeNode === routeNode
          }
          if (logisticsStatus != null) {
            hitLogisticsStatus = data?.logisticsStatus === logisticsStatus
          }
          return hitLogisticsStatus && hitRouteNode && hitTemplateCn && (onlySelected ? !!node.isSelected() : true)
        }
        return true
      },
    )

    // 固定行勾选列
    const onGridReady = useMemoizedFn<NonNullable<ICusAgGridProps<IRoute>['onGridReady']>>(({ api }) => {
      api.setColumnsPinned([api.getColumnState()[0].colId], 'left')
    })

    // 请求数据
    useEffect(() => {
      setLoading(true)
      apiGetRouteList(waybillNo)
        .then(res => setData(res))
        .finally(() => setLoading(false))
    }, [waybillNo])

    return (
      <Modal
        title="添加路由"
        width={1350}
        open={open}
        onCancel={onHide}
        afterOpenChange={afterOpenChange}
        okButtonProps={{ disabled: !selectedLen, loading: submitting }}
        onOk={async () => {
          const selectedRows = gridRef.current?.api.getSelectedRows()
          if (!selectedRows?.length) return
          try {
            setSubmitting(true)
            await apiAddRoute(
              waybillNo,
              selectedRows.map(d => d.routeId),
            )
            onHide()
            onSuccess?.()
          } finally {
            setSubmitting(false)
          }
        }}
        footer={(_originNode, { OkBtn, CancelBtn }) => (
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <Space>
              <Button
                type="link"
                onClick={() => {
                  gridRef.current?.api.getSelectedNodes().forEach(node => node.setSelected(false))
                }}
              >
                取消选中
              </Button>
              <span>
                已选中<b>{selectedLen}</b>条
              </span>
            </Space>
            <Space>
              <CancelBtn />
              <OkBtn />
            </Space>
          </div>
        )}
      >
        <Space style={{ marginBottom: 8 }} size={15}>
          <Space>
            中文模板
            <Input
              style={{ width: 224 }}
              allowClear
              placeholder="请输入中文模板"
              value={filterValueRef.current.templateCn}
              onChange={e => {
                filterValueRef.current = { ...filterValueRef.current, templateCn: e.target.value.trim() }
                update()
                handleDebounceFilter()
              }}
            />
          </Space>
          <Space>
            路由节点
            <Select<number>
              style={{ width: 180 }}
              allowClear
              placeholder="请选择路由节点"
              options={getRouteNodeName.valueList.map(v => ({ label: getRouteNodeName(v), value: v }))}
              value={filterValueRef.current.routeNode}
              onChange={v => {
                filterValueRef.current = { ...filterValueRef.current, routeNode: v }
                update()
                handleFilter()
              }}
            />
          </Space>
          <Space>
            物流状态
            <Select<number>
              style={{ width: 180 }}
              allowClear
              placeholder="请选择物流状态"
              options={getLogisticsStatusName.valueList2.map(v => ({ label: getLogisticsStatusName(v), value: v }))}
              value={filterValueRef.current.logisticsStatus}
              onChange={v => {
                filterValueRef.current = { ...filterValueRef.current, logisticsStatus: v }
                update()
                handleFilter()
              }}
            />
          </Space>
          <Checkbox
            checked={filterValueRef.current.onlySelected}
            onChange={e => {
              filterValueRef.current = { ...filterValueRef.current, onlySelected: e.target.checked }
              update()
              handleFilter()
            }}
          >
            仅显示已选中
          </Checkbox>
          <Button
            onClick={() => {
              filterValueRef.current = { logisticsStatus: null, routeNode: null, templateCn: '', onlySelected: false }
              update()
              handleFilter()
            }}
          >
            重置
          </Button>
        </Space>
        <div style={{ height: 500 }}>
          <CusAgGrid<IRoute>
            ref={gridRef}
            loading={loading}
            rowData={data}
            defaultColDef={defaultColDef}
            columnDefs={columnDefs}
            rowSelection={rowSelection}
            onRowSelected={onRowSelected}
            isExternalFilterPresent={isExternalFilterPresent}
            doesExternalFilterPass={doesExternalFilterPass}
            onGridReady={onGridReady}
          />
        </div>
      </Modal>
    )
  },
  {
    open: (props: IAddRouteModalProps) => {
      updatePopup(<AddRouteModal {...props} destroy={() => updatePopup(null)} />)
    },
  },
)
